#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <errno.h>

#include "err_handling.h"
#include "set_nonblock.h"

#define BUF_SIZE 4
#define EPOLL_SIZE 50

int str_deal(char *msg, int fd);

int socks_clnt[50];
int clnt_cnt = 0;
char names[50][20];

int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    int recv;
    struct sockaddr_in serv_adr, clnt_adr;
    int clnt_adr_sz;
    char msg_recv[256], msg_send[256];
    char name[20];
    struct epoll_event event;
    struct epoll_event ep_events_buf[EPOLL_SIZE] = {0};
    int event_cnt = EPOLL_SIZE;
    int epfd;
    int i, j;

    if (argc != 2)
    {
        printf("Usage:%s <port>\n", argv[0]);
        exit(0);
    }

    serv_sock = socket(PF_INET, SOCK_STREAM, 0);

    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_adr.sin_port = htons(atoi(argv[1]));

    if (bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1)
        error_handling("bind() error");
    if (listen(serv_sock, 5) == -1)
        error_handling("listen() error");
    set_nonblock(serv_sock);
    epfd = epoll_create(EPOLL_SIZE);
    event.events = EPOLLIN;
    event.data.fd = serv_sock;
    epoll_ctl(epfd, EPOLL_CTL_ADD, serv_sock, &event);

    while (1)
    {
        event_cnt = epoll_wait(epfd, ep_events_buf, EPOLL_SIZE, -1);
        if (event_cnt == -1)
            error_handling("epoll_wait() error");

        for (i = 0; i < event_cnt; i++)
        {
            if (ep_events_buf[i].data.fd == serv_sock)
            {
                clnt_sock = accept(serv_sock, NULL, NULL);
                if (clnt_sock == -1)
                    error_handling("accept() error");
                set_nonblock(clnt_sock);
                event.events = EPOLLIN | EPOLLET;
                event.data.fd = clnt_sock;
                epoll_ctl(epfd, EPOLL_CTL_ADD, clnt_sock, &event);
                socks_clnt[clnt_cnt] = clnt_sock;
                clnt_cnt++;
                printf("%d connected\n", clnt_sock);
            }
            else
            {
                recv = read(ep_events_buf[i].data.fd, msg_recv, BUF_SIZE);
                if (recv == -1)
                {
                    if (errno == EAGAIN)
                    {
                        break;
                    }
                    error_handling("read() error");
                }
                else if (recv == 0)
                {
                    epoll_ctl(epfd, EPOLL_CTL_DEL, ep_events_buf[i].data.fd, NULL);
                    close(ep_events_buf[i].data.fd);
                    printf("%d disconnect\n", ep_events_buf[i].data.fd);
                }
                else
                {
                    int ko;
                    msg_recv[recv] = 0;
                    printf(">>>recv:%s", msg_recv);
                    ko = str_deal(msg_recv, ep_events_buf[i].data.fd);
                    if (ko == 1)
                    {
                        for (j = 0; j < clnt_cnt; j++)
                            write(socks_clnt[j], msg_recv, strlen(msg_recv));
                    }
                    else if (ko == 0)
                    {
                        ;
                    }
                    else if (ko == ep_events_buf[i].data.fd)
                    {
                        write(ep_events_buf[i].data.fd, "您@的用户暂未加入聊天室\n", strlen("您@的用户暂未加入聊天室\n"));
                    }
                    else
                    {
                        write(ko, msg_recv, strlen(msg_recv));
                    }
                }
            }
        }
    }
    close(serv_sock);
    close(epfd);
    return 0;
}
int str_deal(char *msg, int fd)
{
    int i, j = 0, k;
    int begin, end;
    char name[20];
    char msg_cpy[50];
    char judge;
    char name_recv[20];
    for (i = 0; msg[i] != '\0'; i++)
    {
        if (msg[i] == ']')
        {
            judge = msg[i + 2];
            break;
        }
    }
    for (i = 0; msg[i] != '\0'; i++)
    {
        if (msg[i] == ']')
        {
            i = i + 2;
            for (j = 0; msg[i] != '\0'; j++)
            {
                msg_cpy[j] = msg[i];
                i++;
            }
            msg_cpy[j] = '\0';
            if (strcmp(msg_cpy, "Hello server") == 0)
                return 0;
            break;
        }
    }
    for (i = 0; msg[i] != '\0'; i++)
    {
        if (msg[i] == '[')
            begin = i;
        if (msg[i] == ']')
            end = i;
    }
    j = 0;
    for (i = begin + 1; i < end; i++)
    {
        name[j] = msg[i];
        j++;
    }
    name[j] = '\0';
    for (i = 0; i < clnt_cnt; i++)
    {
        if (fd == socks_clnt[i])
            strcpy(names[i], name);
    }
    if (judge == '@')
    {
        for (i = 0; msg[i] != '\0'; i++)
        {
            if (msg[i] == '@')
            {
                i++;
                for (k = 0; msg[i] != ':'; k++)
                {
                    name_recv[k] = msg[i];
                    i++;
                }
                name_recv[k] = '\0';
                printf("\n**********recv Name:%s\n", name_recv);
                break;
            }
        }
        printf("pravite chat\n");
        for (i = 0; i < clnt_cnt; i++)
        {
            if (strcmp(names[i], name_recv) == 0)
                return socks_clnt[i];
        }
        return fd;
    }
    else
    {
        printf("room chat\n");
        return 1;
    }
}